#pragma once
#include "ncti_base.h"
#include <NctiPosition.h>
#include "NctiVector.h"

namespace NCTI
{
    /**
    * @brief mesh element fro data exchange
    */
    class DECL_NCTI_BASE NctiMeshElement {
    public:

        /**
        * @brief construct mesh element
        * @param[in] i_type element type
        * @param[in] i_data element node index array
        * @param[in] i_bias first node number
        */
        NctiMeshElement(NctiElementType i_type, const Ncti_UInteger* i_data, Ncti_UInteger i_bias);

        /**
        * @brief get element type
        * @return NctiElementType
        */
        NctiElementType Type()const;

        /**
        * @brief get all node numbers
        * @details the order is in T/DISA 1231.21-2024,7.2.2.2
        * @return NodeNumbers in order
        */
        std::vector<Ncti_UInteger> AllNode()const;

        /**
        * @brief get node count
        */
        Ncti_Size NumberOfVertex()const;

        /**
        * @brief get sub face count
        */
        Ncti_Size NumberOfFace()const;

        /**
        * @brief get sub edge count
        */
        Ncti_Size NumberOfEdge()const;

        /**
        * @brief if is high order element
        */
        Ncti_Boolean HighOrder()const;

        /**
        * @brief the sub face hash
        * @param[in] i_index face index
        */
        size_t HashFace(Ncti_UInteger i_index)const;

        /**
        * @brief the sub edge hash
        * @param[in] i_index edge index
        */
        size_t HashEdge(Ncti_UInteger i_index)const;

        /**
        * @brief get sub face nodes
        * @param[in] i_index face index
        * @param[out] o_face all nodes number in the face
        */
        void SubFace(Ncti_UInteger i_index, std::vector<Ncti_UInteger>& o_face)const;

        /**
        * @brief get sub face high nodes
        * @param[in] i_index face index
        * @param[out] o_face high order nodes number in the face
        */
        void  HighFace(Ncti_UInteger i_index, std::vector<Ncti_UInteger>& o_face)const;

        /**
        * @brief get sub face low nodes
        * @param[in] i_index face index
        * @param[out] o_face low order nodes number in the face
        */
        void  LowFace(Ncti_UInteger i_index, std::vector<Ncti_UInteger>& o_face)const;

        /**
        * @brief get sub face with out number
        * @details used in display
        * @param[in] i_index face index
        * @param[out] o_face nodes index
        */
        int  DispFace(Ncti_UInteger i_index, std::vector<Ncti_UInteger>& o_face)const;

        /**
        * @brief get sub face nodes
        * @param[in] i_index face index
        * @param[out] o_face all nodes number in the face
        */
        void SubEdge(Ncti_UInteger i_index, std::vector<Ncti_UInteger>& o_edge)const;

        /**
        * @brief get element edge from sub face edge 
        * @param[in] findex face index
        * @param[in] eindex the edge index in the face
        * @return the edge index in th element
        */
        Ncti_UInteger SubFaceEdgeNum(Ncti_UInteger findex, Ncti_UInteger eindex)const;

        /**
        * @brief get edge index in sub face from element edge 
        * @param[in] findex face index
        * @param[in] enumber the edge number in the element
        * @return the edge index in th face
        */
        int SubFaceEdgeIndex(Ncti_UInteger findex, Ncti_UInteger enumber)const;

        /**
         * @brifef get center for element or sub face or sub edge
         * @param [in] subid subid for edge or face.-1 for all element
         * @param [in] isedge subid is edge or face
         * @param [out] if not nullptr,norm normal for face
         * @return center
         */
        NctiPosition GetCenter(int subid, bool isedge, NctiVector* norm)const;

    private:
        Ncti_UInteger m_bias{ 0 };
        NctiElementType m_type;
        const Ncti_UInteger* m_data{ nullptr };
    };
};

